package com.yc.config;

import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.ElasticsearchException;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import dev.langchain4j.store.embedding.elasticsearch.ElasticsearchEmbeddingStore;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;

@Configuration
public class ElasticsearchConfig {
    private static final Logger logger = LoggerFactory.getLogger(ElasticsearchConfig.class);

    @Value("${elasticsearch.host:http://localhost:9200}")
    private String elasticsearchHost;  //Elasticsearch 的主机地址

    @Value("${elasticsearch.index.name:no-auth-index}")
    private String indexName; //索引名

    //创建 RestClient 实例，连接 Elasticsearch
    @Bean
    public RestClient restClient() {
        logger.info("Creating Elasticsearch RestClient with host: {}", elasticsearchHost);
        return RestClient.builder(HttpHost.create(elasticsearchHost)).build();
    }

   // 创建 ElasticsearchClient（高级客户端，用于操作索引等功能）
    @Bean
    public ElasticsearchClient elasticsearchClient(RestClient restClient) {
        logger.info("Creating ElasticsearchClient");
        return new ElasticsearchClient(new RestClientTransport(
                restClient,
                new JacksonJsonpMapper()
        ));
    }

    @Bean
    public ElasticsearchEmbeddingStore elasticsearchEmbeddingStore(ElasticsearchClient client) {
        try {
            logger.info("Creating Elasticsearch index: {}", indexName);
            // 创建一个 Elasticsearch 索引（名字是 indexName）,
            client.indices().create(c -> c
                    .index(indexName)
                    .mappings(m -> m
                            .properties("embedding", p -> p  //"embedding" 是这个索引中定义的一个字段（field）名，它的作用是：用来存储文本或文档的“向量表示”，也叫“嵌入向量“
                                    .denseVector(dv -> dv
                                            .dims(1024)         // 向量维度 1024
                                            .index(true)        // 启用向量索引功能
                                            .similarity("cosine") // 使用余弦相似度计算
                                    )
                            )
                    )
            );

        } catch (ElasticsearchException e) {
            if (!e.getMessage().contains("resource_already_exists_exception")) {
                throw e;
            }
        } catch (IOException e) {
            throw new RuntimeException("创建 Elasticsearch 索引失败", e);
        }

        logger.info("返回 ElasticsearchEmbeddingStore 实例");
        // 构建并返回一个 ElasticsearchEmbeddingStore 对象
        // 这个对象 LangChain4j 可以用来存储和检索向量
        return ElasticsearchEmbeddingStore.builder()
                .serverUrl(elasticsearchHost)  // 设置连接的 Elasticsearch 地址
                .indexName(indexName)          // 设置要使用的索引名称
                .build();
    }
}
